package exi;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.sax.SAXSource;

import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;

import com.siemens.ct.exi.EXIFactory;
import com.siemens.ct.exi.GrammarFactory;
import com.siemens.ct.exi.api.sax.EXIResult;
import com.siemens.ct.exi.api.sax.EXISource;
import com.siemens.ct.exi.exceptions.EXIException;
import com.siemens.ct.exi.grammar.Grammar;
import com.siemens.ct.exi.helpers.DefaultEXIFactory;

import domainspecific.types.MeterReadings;

import generic.ConnectionHandler;
import generic.Request;

public class ExiHandler extends ConnectionHandler {

	@Override
	public void run() {
		try {
			// First, grab the Request from the Socket
			InputStream in = this.socket.getInputStream();
			OutputStream out = this.socket.getOutputStream();
			
			GrammarFactory gf = GrammarFactory.newInstance();
			Grammar grammar;
			try {
				grammar = gf.createGrammar("exischema.xsd");
			} catch (EXIException e) {
				grammar = null;
				e.printStackTrace();
				System.err.println("Could not parse grammar: " + e.getMessage());
			}
			EXIFactory exiFactory;
			exiFactory = DefaultEXIFactory.newInstance();
			exiFactory.setGrammar(grammar);
			
			EXISource saxSource = new EXISource(exiFactory);
			XMLReader xmlReader = saxSource.getXMLReader();
			SAXSource exiSource = new SAXSource(new InputSource(in));
			exiSource.setXMLReader(xmlReader);
			JAXBContext jcontext = JAXBContext.newInstance(Request.class,
					MeterReadings.class);
			Unmarshaller unmarshal = jcontext.createUnmarshaller();
			while (true) {
				Request request = (Request) unmarshal.unmarshal(exiSource);
				// System.out.println("Handling request for id " +
				// request.getId());
 
				EXIResult exiResult = new EXIResult(exiFactory);
				exiResult.setOutputStream(out);
				Marshaller marshal = jcontext.createMarshaller();
				marshal.marshal(new MeterReadings(request.getNumReadings()), exiResult.getHandler());
			}

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (EXIException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (TransformerFactoryConfigurationError e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (JAXBException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}
